package com.fast.develop.meta.dm.configuration;

import com.fast.develop.api.DomainModelFastDevelopConfiguration;
import com.fast.develop.core.plugin.PluginRegister;
import com.fast.develop.integration.web.MvcMappingHandlerMapping;
import com.fast.develop.meta.base.MetaConfiguration;
import com.fast.develop.meta.dm.configuration.annotation.EnableDomainModel;
import com.fast.develop.meta.dm.configuration.properties.DomainModelPropesties;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ImportAware;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import javax.sql.DataSource;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;


/**
 * @author 莫寅
 * 领域模型自动装配
 */
//@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties({DomainModelPropesties.class})
@Slf4j
@ConditionalOnClass({RequestMappingHandlerMapping.class})
public class DomainModelAutoConfiguration implements ImportAware {


    private DataSource dataSource;

    private DomainModelPropesties domainModelPropesties;

    protected RequestMappingHandlerMapping requestMappingHandlerMapping;

    private Map annotationProperties;

    private DomainModelFastDevelopConfiguration domainModelFastDevelopConfiguration;

    /**
     * 请求拦截器
     */
    private final ObjectProvider<List<PluginRegister>> luginRegisterProvider;


    private MetaConfiguration metaConfiguration;

    public DomainModelAutoConfiguration(
            MetaConfiguration metaConfiguration,
            DataSource dataSource,
            DomainModelPropesties domainModelPropesties,
            RequestMappingHandlerMapping requestMappingHandlerMapping,
            ObjectProvider<List<PluginRegister>> luginRegisterProvider
    ) {
        this.metaConfiguration = metaConfiguration;
        this.luginRegisterProvider = luginRegisterProvider;
        this.dataSource = dataSource;
        this.domainModelPropesties = domainModelPropesties;
        this.requestMappingHandlerMapping = requestMappingHandlerMapping;

        //加载模式
        initDomainModelFastDevelopConfiguration();
    }



    @SneakyThrows
    private void initDomainModelFastDevelopConfiguration(){
        DomainModelFastDevelopConfiguration domainModelFastDevelopConfiguration = new DomainModelFastDevelopConfiguration(
                metaConfiguration,
                dataSource,
                requestMappingHandlerMapping,
                luginRegisterProvider
        );

        this.domainModelFastDevelopConfiguration = domainModelFastDevelopConfiguration;
    }


//    @Bean
//    public MvcMappingHandlerMapping mvcMappingHandlerMapping(){
//        return domainModelFastDevelopConfiguration.getMvcMappingHandlerMapping();
//    }


    @Bean
    public DomainModelFastDevelopConfiguration domainModelFastDevelopConfiguration(){
        domainModelFastDevelopConfiguration
                .domainProperties(domainModelPropesties)
                .packagesToScan(getPackagesToScan())
                .annotatedClasses(getAnnotatedClasses())
                .mappingResources(getMappingResources())
                .showSql(domainModelPropesties.isShowSql())
                .ddlAuto(domainModelPropesties.getDdlAuto());
        return domainModelFastDevelopConfiguration;
    }



    private String[] getPackagesToScan(){
        if(annotationProperties == null){
            return domainModelPropesties.getPackagesToScan();
        }

        LinkedList packagesToScan = ((LinkedList)annotationProperties.get("packagesToScan"));
        if(((String[])packagesToScan.get(0)).length != 0){
            return (String[]) packagesToScan.get(0);
        }else{
            return domainModelPropesties.getPackagesToScan();
        }
    }


    private Class[] getAnnotatedClasses(){
        if(annotationProperties == null){
            return domainModelPropesties.getAnnotatedClasses();
        }

        LinkedList annotatedClasses = ((LinkedList)annotationProperties.get("annotatedClasses"));
        if(((Class[])annotatedClasses.get(0)).length != 0){
            return (Class[]) annotatedClasses.get(0);
        }else{
            return domainModelPropesties.getAnnotatedClasses();
        }
    }

    private String[] getMappingResources(){
        if(annotationProperties == null){
            return domainModelPropesties.getMappingResources();
        }

        LinkedList mappingResources = ((LinkedList)annotationProperties.get("mappingResources"));
        if(((String[])mappingResources.get(0)).length != 0){
            return (String[]) mappingResources.get(0);
        }else{
            return domainModelPropesties.getMappingResources();
        }
    }

    @Override
    public void setImportMetadata(AnnotationMetadata importMetadata) {
        annotationProperties = importMetadata.getAllAnnotationAttributes(EnableDomainModel.class.getName());
    }

}
